#include "link_list.h"

// 单链表的创建
Link_list* init_link_list(void)
{
    // 1 创建 头节点的动态空间
    Link_list *list = (Link_list *)malloc(sizeof(Link_list));
    //安全判断
    if (NULL == list)
    {
        printf("头结点创建失败!\n");
        return NULL;
    }
     //如果成功则初始化链表中的头节点为 NULL
    list->next = NULL;
    return list;
}

// 单链表的销毁
void free_link_list(Link_list ** list)
{
    if (NULL==*list)
    {
        printf("表为NULL,无需销毁\n");
        return;
    }

    // 1 销毁结点
    Node *p1 = (*list)->next;
    Node *p2 = p1->next;
    for (int i = 0; p1->next!=NULL; i++)
    {
        free(p1);
        p1 = p2;
        // if 判断  判断 p2 = NULL 的时候 我们如何处理
        if (NULL!=p2)
        {
            p2 = p2->next;
        }
     
    }
    // 2 销毁头结点
    free(*list);
    *list = NULL;
}

//  单链表的遍历
void print_link_list(Link_list *list)
{
   //判空
   IsEmpty_Sql_List(list);
   Node *p = list->next;        //用于遍历
   while (p!= NULL)
   {
       printf("姓名:%s 性别:%s 年龄:%d 成绩:%d 学号:%d\n",
              p->data.name, p->data.sex, p->data.age,
              p->data.sco, p->data.id);
       p = p->next;
   }
}

// 单链表的判空
int IsEmpty_Sql_List(Link_list *list)
{
    if (NULL==list||list->next==NULL)
    {
        printf("单链表为NULL!\n");
        return 0;
    }
    return 1;
}

// 尾插
void tail_insert_node(Link_list *list, Elenemt_data data)
{
   
    // 生成一个新节点
    Node *new = (Node *)malloc(sizeof(Node));
    //特殊情况只有一个头结点
    if (list->next==NULL)
    {
        list->next = new;
        // 要插入的数据存放在新节点
        new->data = data;
        // 将新节点插入到链表尾部
        new->next = NULL; // 尾结点置空
        return;
    }

    Node *p = list->next; // 用于遍历
    //遍历至最后一个节点元素
    while (p->next != NULL)
    {
        p = p->next;
    }
    //要插入的数据存放在新节点
    new->data = data;
    // 将新节点插入到链表尾部
    p->next = new;
    new->next = NULL;//尾结点置空
    return;
}

// 单链表的查找
Node *find_node_id(Link_list *list, int index)
{
    //安全判断
    IsEmpty_Sql_List(list);
    //判断输入的indnex是否合法
    if (index<0)
    {
        printf("index值非法!\n");
        exit(-1);
    }

    Node *p = list->next;
    int pos = 1;        // 用于记录位置
    while (pos!=index)
    {
        p = p->next;
        pos++;
        //安全判断
        if (p == NULL)
        {
            printf("查找的位置非法\n");
            exit(-1);
        }
    }
    //返回第index结点的地址
    return p;
}
//按值查找
Node *find_node_name(Link_list *list, char *name)
{
    // 安全判断
    IsEmpty_Sql_List(list);
    Node *p = list->next;
    while (strcmp(p->data.name,name))
    {
        p = p->next;
        if (p==NULL)
        {
            printf("抱歉,查无此人!\n");
            exit(-1);
        }   
    }
    return p;
}

// 任意插
void insert_node(Link_list *list, Elenemt_data data, int index)
{
    //安全判断
    if (NULL==list)
    {
        printf("链表为NULL!\n");
    }
    // 生成新结点
    Node *new_node = (Node *)malloc(sizeof(Node));

    //
    index=index-1;
    //插到头结点后
    if (index==0)
    {
        new_node->data = data; // 赋值
        new_node->next = list->next;        // 将新节点链接到头结点的后一位
        list->next = new_node;             // 将新节点链接上
        return;
    }
    
    //只有一个头结点的情况
    if (NULL==list->next)
    {
        new_node->data = data;     // 赋值
        list->next = new_node;    // 将新节点链接上
        new_node->next = NULL;
        return;
    }

    //先找到插入位置的前一个结点
    Node *p = find_node_id(list,index);
  
    new_node->data = data;    //赋值
    new_node->next = p->next;//将新节点链接到p结点的后一位
    p->next = new_node;     //将新节点链接上
    return;
}

// 尾删
void tail_delete_node(Link_list *list)
{
    // 安全判断
    IsEmpty_Sql_List(list);
    // 特殊情况只有一个头结点
    if (list->next == NULL)
    {
        //头结点置空
        free(list);
        list = NULL;
        return;
    }
    Node *p = list->next;   // 用于遍历
    Node *del = p->next;    // 用于删除最后一个结点
    // 遍历至最后一个节点元素前一个结点
    while (del->next != NULL)
    {
        p = p->next;
        del = del->next;
    }
    //删除最后一个结点
    p->next = NULL;
    free(del);
    del = NULL;
}

//任意删除
void delete_node(Link_list *list, int index)
{
    // 安全判断
    if (NULL == list)
    {
        printf("链表为NULL!\n");
        return;
    }
    //接收删除的结点
    Node *del_p = NULL;
    //
    index = index - 1;
    // 删除第一个元素
    if (index == 0)
    {
        del_p = list->next;
        list->next = del_p->next; // 改指向
        //释放删除的结点
        free(del_p);
        del_p->next = NULL;
        return;
    }

    // 只有一个头结点的情况
    if (NULL == list->next)
    {
       //直接删除头结点
       free(list);
       list = NULL;
       return;
    }

    // 先找到删除位置的前一个结点
    Node *p = find_node_id(list, index);

    //改指向
    del_p = p->next;
    p->next = del_p->next; // 改指向
    // 释放删除的结点
    free(del_p);
    del_p->next = NULL;
    return;
}